<template>
  <div class="content" id="content">

    <el-icon :size="32" class="close">
      <FullScreen @click="setFullScreenMain" />
      <CloseBold @click="close" />
    </el-icon>
    <div class="select_box" v-show="!user || !show">
      <template v-if="!user">
        <h3>请选择身份</h3>
        <div class="select_box_item">
          <p @click="selectClick('x')" class="select_item_black"></p>
          <p @click="selectClick('o')" class="select_item_white"></p>
          <p @click="selectClick('look')" class="select_item_look">观众</p>
        </div>
      </template>
      <template v-else>
        <h3>请输入服务器域名</h3>
        <el-input v-model="originValue" style="width: 80%" @keyup.enter="creatWebsocket" placeholder="回车确认" />
      </template>
    </div>
    <div class="top" v-show="!!user && show">
      <div class="left">
        <p class=" select_item_black" :class="[onlines.x?'on_line':'off_line']"></p>
        <p class="msg" v-if="isShowText.x">{{ isShowText.x }}</p>
      </div>
      <div class="center">
        <el-button type="success" style="width: 100px; margin-bottom: 5px" @click="reload" v-if="win">重新开始</el-button>
        <el-button type="danger" @click="surrender" style="width: 100px; margin-bottom: 5px"
                   v-if="!win && user !== 'look'">我要投降</el-button>
        <el-input v-model="msgValue" @keyup.enter="sendText" placeholder="回车发送消息" />
      </div>
      <div class="right">
        <p class="msg" v-if="isShowText.o">{{ isShowText.o }}</p>
        <p class=" select_item_white" :class="[onlines.o?'on_line':'off_line']"></p>
      </div>
    </div>
    <div v-show="!!user && show" class="gobang_box" id="gobang_box" :style="{ 'background-image': `url(${bgUrl})` }"
         v-ripple>
      <div class="box" v-for="(item, index) in arr" :key="index">
        <div class="box_item" v-for="(jtem, jndex) in item" :key="jndex">
          <piece_item @success="success" :value="jtem" :position="{ x: jndex, y: index }"
                      :isNullCity="nullCityArr.length" :active="getActive({ x: jndex, y: index })"
                      :disabled='!onlines.x||!onlines.o' :win="win">
          </piece_item>
        </div>
      </div>
    </div>
  </div>
  <!-- <Particles /> -->
</template>

<script setup>
import { ElMessage, ElNotification, ElMessageBox } from "element-plus";
import { closeMain, setFullScreen } from "./utils/useIPC.js";
import { initTopDrag } from "./utils/utils.js";
import { reactive, ref, onMounted } from "vue";
import Piece_item from "./components/piece_item.vue";
// import Particles from "./components/Particles";
import checkFile from "@/utils/fileCheck.js";
onMounted(() => {
  initTopDrag();
});
let user = ref("");
let msgValue = ref("");
let originValue = ref("");
let originLocalStoge = JSON.parse(localStorage.getItem("originValue"));
if (originLocalStoge) {
  originValue.value = originLocalStoge;
}
let show = ref(false);
let nullCityArr = ref([]);
let nullCity = ref({});
// 聊天信息
let isShowText = reactive({
  x: "",
  o: "",
});
// 选手状态
let onlines = reactive({
  x: false,
  o: false,
});
let bgUrl = require("@/assets/bg.png");
user.value = JSON.parse(sessionStorage.getItem("user"));
sessionStorage.setItem("Prev", JSON.stringify("o"));
let websocket = "";
let prevPosition = ref({});

let creatWebsocket = () => {
  localStorage.setItem("originValue", JSON.stringify(originValue.value));
  websocket = new WebSocket(`ws://${originValue.value}:8000/${user.value}`);
  // 打开事件
  websocket.onopen = function () {
    // 获取当前链接的状态
    // 1 是建立了链接
    let cache = [
      {
        fn: ({ show, readyState }) => {
          show.value = readyState == 1;
          return readyState !== 1;
        },
        options: {
          show: show,
          readyState: websocket.readyState,
          msg: "链接失败",
        },
      },
    ];
    console.log(websocket.readyState);
    new checkFile(cache).check();
  };
  // 接收服务器返回的消息
  websocket.onmessage = function (data) {
    // 服务器返回过来的聊天信息
    const {
      code,
      name,
      form,
      text,
      isNull,
      nullCity: myNullCity,
      win: myWin,
      key,
      prevPosition: myPrevPosition,
      list,
      fatalMoveArr,
      isSurrender,
      names,
    } = JSON.parse(data.data);
    console.log(JSON.parse(data.data));
    let showMsg = (message, type = "warning", showClose = "true") => {
      ElMessage({
        message,
        type,
        showClose,
      });
    };
    let cache = {
      "-1": () => {
        removeUser();
        showMsg("用户已存在，请重新选择");
      },
      "-2": () => {
        showMsg(`用户${name}下线了`);
      },
      1: () => {
        if (user.value !== "look") {
          names.forEach((item) => {
            onlines[item] = true;
          });
          let prev = JSON.parse(sessionStorage.getItem("Prev"));
          websocket.send(JSON.stringify({ list: arr.value, key: prev }));
        }
      },
      2: () => {
        if (form !== "look") {
          isShowText[form] = text;
          setTimeout(() => {
            isShowText[form] = "";
          }, 2000);
        } else {
          ElNotification({
            title: "观众说",
            message: text,
            position: "top-left",
            offset: 300,
            duration: 2000,
          });
        }
      },
      3: () => {
        if (form == user.value) {
          lifeOrdeath(fatalMoveArr);
          showMsg("恭喜你触发绝杀，等待对方做出决断", "success");
        }
      },
      4: () => {
        if (!(form !== user.value && user.value !== "look")) {
          nullCityArr.value = fatalMoveArr;
          nullCity.value = myNullCity;
          showMsg(`对手使用空城计`);
        }
      },
    };
    if (code) {
      cache[`${code}`]();
    }
    if (key) {
      sessionStorage.setItem("Prev", JSON.stringify(key));
    }
    if (!(key && myPrevPosition)) {
      prevPosition.value = prevPosition;
    }
    if (list && !win.value && fatalMoveArr) {
      nullCityArr.value = [];
      nullCity.value = {};
    }
    if (list) {
      arr.value = list;
      sessionStorage.setItem("arr", JSON.stringify(arr.value));
    }
    win.value = myWin;
    if (win.value) {
      if (!(myWin && isSurrender && win.value == user.value)) {
        showMsg(`${myWin == "x" ? "o" : "x"}发起投降,游戏结束`, "success");
      } else {
        showMsg(`游戏结束，胜利者是${myWin}`);
      }
    }
    console.log("arr", arr.value);
  };
};

let removeUser = () => {
  sessionStorage.removeItem("user");
  user.value = "";
};
let arr = ref(new Array(21).fill(0).map(() => new Array(21).fill(null)));
let list = JSON.parse(sessionStorage.getItem("arr"));
if (list) {
  arr.value = list;
}
// 落子
let success = (e, position) => {
  let isSeeThrough = true;
  if (nullCityArr.value.length) {
    let flag = false;
    nullCityArr.value.map((item) => {
      if (position.x == item.x && position.y == item.y) {
        flag = true;
      }
    });
    if (flag) {
      if (nullCity.value.x == position.x && nullCity.value.y == position.y) {
        arr.value[position.y][position.x] = e;
        ElMessage({
          message: "恭喜你识破了空城计",
          type: "success",
          showClose: true,
        });
      } else {
        isSeeThrough = false;
        ElMessage({
          message: "您未能识破空城计",
          type: "info",
          showClose: true,
        });
      }
    } else {
      arr.value[position.y][position.x] = e;
    }
  } else {
    arr.value[position.y][position.x] = e;
  }
  if (nullCity.value.x && !isSeeThrough) {
    arr.value[nullCity.value.y][nullCity.value.x] = null;
  }
  sessionStorage.setItem("arr", JSON.stringify(arr.value));
  websocket.send(
    JSON.stringify({ list: arr.value, key: e, prevPosition: position })
  );
  if (isWin(position, e) && isSeeThrough) {
    win.value = e;
    sendWin();
    return;
  }
  let fatalMoveArr = fatalMove(position, e);
  if (fatalMoveArr.length == 2) {
    console.log("绝杀");
    let params = {
      code: 3,
      fatalMoveArr,
      form: e,
    };
    websocket.send(JSON.stringify(params));
  }
};

// 选择身份
let selectClick = (key) => {
  user.value = key;
  sessionStorage.setItem("user", JSON.stringify(key));
  sessionStorage.removeItem("arr");
};
// 重新开始
let reload = () => {
  websocket.close();
  sessionStorage.clear();
  sessionStorage.setItem("Prev", JSON.stringify("o"));
  user.value = "";
  arr.value = new Array(21).fill(0).map(() => new Array(21).fill(null));
  win.value = "";
  prevPosition.value = "";
  show.value = false;
  originValue.value = "";
};
// 创建链接
if (user.value) {
  creatWebsocket();
}
// 同步胜利信息
let sendWin = (isSurrender) => {
  websocket.send(JSON.stringify({ win: win.value, isSurrender: isSurrender }));
};
// 聊天
let sendText = () => {
  let params = {
    code: 2,
    text: msgValue.value,
    form: user.value,
  };
  websocket.send(JSON.stringify(params));
};
// 胜利检测
let win = ref("");
let length = 0;
let isWin = (position, type) => {
  // 当前位置
  let y = position.y;
  let x = position.x;
  // 东西南北
  let e = 0;
  let w = 0;
  let s = 0;
  let n = 0;
  // 东西检测
  e = getlength(position, "e", type);
  length = 0;
  w = getlength(position, "w", type);
  length = 0;
  if (e + w + 1 >= 5) {
    return true;
  }
  // 南北检测
  s = getlength(position, "s", type);
  length = 0;
  n = getlength(position, "n", type);
  length = 0;
  if (s + n + 1 >= 5) {
    return true;
  }
  // 东北西南检测
  let en = getlength(position, "en", type);
  length = 0;
  let ws = getlength(position, "ws", type);
  length = 0;
  if (en + ws + 1 >= 5) {
    return true;
  }
  // 西北东南检测
  let wn = getlength(position, "wn", type);
  length = 0;
  let es = getlength(position, "es", type);
  length = 0;
  if (wn + es + 1 >= 5) {
    return true;
  }

  return false;
};
// 绝杀检测
let fatalMove = (position, type) => {
  // 当前位置
  let y = position.y;
  let x = position.x;
  // 东西南北
  let e = 0;
  let w = 0;
  let s = 0;
  let n = 0;
  // 东西检测
  e = getlength(position, "e", type);
  length = 0;
  w = getlength(position, "w", type);
  length = 0;
  if (
    e + w + 1 == 4 &&
    arr.value[y][x + e + 1] == null &&
    arr.value[y][x - w - 1] == null
  ) {
    return [
      {
        y,
        x: x - w - 1,
      },
      {
        y,
        x: x + e + 1,
      },
    ];
  }
  // 南北检测
  s = getlength(position, "s", type);
  length = 0;
  n = getlength(position, "n", type);
  length = 0;

  if (
    s + n + 1 == 4 &&
    arr.value[y + s + 1][x] == null &&
    arr.value[y - n - 1][x] == null
  ) {
    return [
      {
        y: y - n - 1,
        x,
      },
      {
        y: y + s + 1,
        x,
      },
    ];
  }
  // 东北西南检测
  let en = getlength(position, "en", type);
  length = 0;
  let ws = getlength(position, "ws", type);
  length = 0;

  if (
    en + ws + 1 == 4 &&
    arr.value[y - en - 1][x + en + 1] == null &&
    arr.value[y + ws + 1][x - ws - 1] == null
  ) {
    return [
      {
        y: y - en - 1,
        x: x + en + 1,
      },
      {
        y: y + ws + 1,
        x: x - ws - 1,
      },
    ];
  }
  // 西北东南检测
  let wn = getlength(position, "wn", type);
  length = 0;
  let es = getlength(position, "es", type);
  length = 0;
  if (
    wn + es + 1 == 4 &&
    arr.value[y - wn - 1][x - wn - 1] == null &&
    arr.value[y + es + 1][x + es + 1] == null
  ) {
    return [
      {
        y: y - wn - 1,
        x: x - wn - 1,
      },
      {
        y: y + es + 1,
        x: x + es + 1,
      },
    ];
  }
  return [];
};
let getlength = (position, type, name) => {
  console.log("==>", position, type, name);
  let x = position.x;
  let y = position.y;
  // 东
  if (type == "e") {
    x = x + 1;
  }
  // 西
  if (type == "w") {
    x = x - 1;
  }
  // 南
  if (type == "s") {
    y = y + 1;
  }
  // 北
  if (type == "n") {
    y = y - 1;
  }
  // 东北
  if (type == "en") {
    y = y - 1;
    x = x + 1;
  }
  // 西南
  if (type == "ws") {
    y = y + 1;
    x = x - 1;
  }
  // 东南
  if (type == "es") {
    y = y + 1;
    x = x + 1;
  }
  // 西北
  if (type == "wn") {
    y = y - 1;
    x = x - 1;
  }
  if (arr.value[y][x] == name) {
    length++;
    return getlength({ x, y }, type, name);
  } else {
    return length;
  }
};

// 生死选择
const lifeOrdeath = (fatalMoveArr) => {
  ElMessageBox.confirm("对手已触发绝杀，是否使用空城计?", "Warning", {
    confirmButtonText: "确认",
    cancelButtonText: "放弃",
    type: "warning",
  }).then(() => {
    let parms = {
      code: 4,
      isNull: true,
      fatalMoveArr: fatalMoveArr,
      from: user.value,
      key: user.value,
    };
    fatalMoveArr.map(({ x, y }) => {
      arr.value[y][x] = user.value;
    });
    parms.list = arr.value;

    if (Math.random() > 0.5) {
      parms.nullCity = fatalMoveArr[1];
    } else {
      parms.nullCity = fatalMoveArr[0];
    }
    websocket.send(JSON.stringify(parms));
  });
};

const getActive = ({ x, y }) => {
  if (nullCityArr.value.length) {
    let isActive = false;
    nullCityArr.value.map((item) => {
      if (item.x == x && item.y == y) {
        isActive = true;
      }
    });
    return isActive;
  } else {
    return x == prevPosition.value.x && y == prevPosition.value.y;
  }
};

// icp通信关闭应用
let close = () => {
  closeMain();
};

// 投降
let surrender = () => {
  win.value = user.value == "x" ? "o" : "x";
  sendWin(true);
};

// 全屏
let setFullScreenMain = () => {
  setFullScreen();
};
</script>

<style lang="scss" scoped>
// @import url("~@/style/utils.scss");
.close {
  position: absolute;
  right: 20px;
  top: 20px;
  cursor: pointer;
  color: #333;
}
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
}
.content {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  height: 100vh;
  //   -webkit-app-region: drag;
  .top {
    width: 50%;
    display: flex;
    justify-content: space-between;
    align-items: center;
    .left,
    .right {
      display: flex;
      .avatar {
        width: 20px;
        height: 20px;
        border-radius: 5px;
        text-align: center;
        line-height: 20px;
        color: #fff;
        background: #333;
      }
      .msg {
        padding: 10px 10px;
        border: 1px solid var(--el-border-color-light);
        position: relative;
        border-radius: 4px;
        background: #fff;
        &::before {
          position: absolute;
          width: 10px;
          height: 10px;
          z-index: 0;
          content: " ";
          transform: rotate(45deg);
          box-sizing: border-box;
          border: 1px solid var(--el-border-color-light);
          border-right-color: transparent;
          border-top-color: transparent;
          border-bottom-left-radius: 2px;
          background: var(--el-bg-color-overlay);
        }
      }
    }
    .center {
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
    }
    .left {
      .msg {
        left: 5px;
        &::before {
          left: -5px;
          top: 2px;
        }
      }
    }
    .right {
      .msg {
        right: 5px;
        &::before {
          border-color: var(--el-border-color-light);
          border-left-color: transparent !important;
          border-bottom-color: transparent !important;
          right: -5px;
          top: 2px;
        }
      }
    }
  }
}
.select_box {
  width: 300px;
  height: 200px;
  border: 1px solid #ccc;
  text-align: center;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: #fff;
  .select_box_item {
    display: flex;
    justify-content: space-around;
    width: 100%;
    p {
      width: 40px;
      height: 30px;
      border: 1px solid #ccc;
      text-align: center;
      line-height: 30px;
      cursor: pointer;
    }
  }
}
.box {
  display: flex;
  .box_item {
    display: flex;
  }
}
.gobang_box {
  margin-top: 20px;
  background: url("~@/assets/bg.png");
  cursor: pointer;
}
.select_item_black {
  height: 20px;
  width: 20px;
  background: url("./assets/black.png") no-repeat;
  background-size: 20px 20px;
  background-position: center center;
}
.select_item_white {
  height: 20px;
  width: 20px;
  background: url("./assets/white.png") no-repeat;
  background-size: 20px 20px;
  background-position: center center;
}
.on_line {
  position: relative;
  &::before {
    content: "在线";
    display: block;
    position: absolute;
    bottom: -15px;
    left: 0;
    width: 50px;
    font-size: 12px;
    color: green;
  }
}
.off_line {
  position: relative;
  &::before {
    content: "离线";
    display: block;
    position: absolute;
    bottom: -15px;
    left: 0;
    color: red;
    width: 50px;
    font-size: 12px;
  }
}
</style>
